package com.handsoninfo;


import net.sourceforge.tess4j.Word;

import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

class Division {
    Map<Rectangle, Integer> mapRectangle = new HashMap<>();
    Map<Word, Integer> mapWord = new HashMap<>();
    java.util.List<Block> blocks = new ArrayList<>();

    public Division(java.util.List<Word> blocks) {
        for (Word div : blocks) {
            Rectangle rect = div.getBoundingBox();
            int area = rect.width * rect.height;
            if (area < 2 * 5) continue;
            this.blocks.add(new Block(div));
        }
    }

    public int size() {
        return blocks.size();
    }

    public int blueSize() {
        int ret = 0;
        for (Block block : blocks) {
            if (block.rawBlue.size() > 0) {
                ret += 1;
            }
        }
        return ret;
    }

    public Iterable<Block> getBlocks() {
        return () -> new Iterator<Block>() {

            int i = 0;

            @Override
            public boolean hasNext() {
                return i < blocks.size();
            }

            @Override
            public Block next() {
                Block ret = new Block(blocks.get(i));
                i += 1;
                return ret;
            }
        };
    }

    public void putWord(Boolean isBlue, Word word) {
        if (null == isBlue) return;

        for (int i = 0; i < blocks.size(); i += 1) {
            Block block = blocks.get(i);
            if (block.rect.contains(word.getBoundingBox())) {
                if (isBlue) {
                    block.addBlue(word.getText());
                } else {
                    block.addBlack(word.getText());
                }
                mapRectangle.put(word.getBoundingBox(), i);
                mapWord.put(word, i);
                return;
            }
        }
    }

    public Normalized normalize() {
        Block lastBlock = null;
        List<Block> retList = new ArrayList<>();
        for (Block block : getBlocks()) {
            if (block.rawBlue.size() == 0) {
                if (null != lastBlock) {
                    lastBlock.raw += block.raw;
                    lastBlock.value += block.value;
                }
                continue;
            }
            lastBlock = block;
            retList.add(block);
        }
        return new Normalized(retList);
    }

    public boolean containsWord(Word word) {
        return mapWord.containsKey(word);
    }

    static class Normalized {
        private final List<Block> blocks;
        private Normalized(List<Block> blocks) {
            if (blocks.size() != 5) {
                System.out.println("blocks.size():" + blocks.size());
                throw new IllegalArgumentException();
            }
            this.blocks = blocks;
        }

        public String getAddress() {
            return blocks.get(3).value;
        }

        public String getNum() {
            return blocks.get(4).value;
        }
    }

    static class Block {
        String raw;
        String key = "";

        String value = "";

        List<String> rawBlue = new ArrayList<>();

        Rectangle rect;

        public Block(Word word) {
            raw = word.getText();
            rect = word.getBoundingBox();
        }

        public Block(Block block) {
            raw = block.raw;
            key = block.key;
            value = block.value;
            rawBlue = new ArrayList<>(block.rawBlue);
            rect = new Rectangle(block.rect);
        }

        public void addBlack(String text) {
            //        System.out.println(text);
            value += text;
        }

        public void addBlue(String text) {
            //        System.out.println(text);
            key += text;
            rawBlue.add(text);
        }

        public Rectangle getRect() {
            return new Rectangle(rect);
        }
    }
}
